import json

from app.lib.txt import num_get
from app.model import mysql
from app.service.comment import get_comment_object_first_comment, is_like_comment
from app.service.folder import get_folder, get_folder_covers
from app.service.format_datetime import format_datetime
from app.service.media import is_collect_media, is_like_media, get_media_custom_tags
from app.service.menu import nav_name
from app.service.recycle import get_user_recycle_count, get_user_recycles
from app.service.user import get_user_base_info, format_avatar_url, get_follow_status
from app.settings.config import QINIU_MEDIA_HOST
from app.service import menu as menu_service


async def format_navs(menu_id):
    nav_name = [[{"id": item["id"], "name": item["name"]}] for item in
                await menu_service.nav_name(menu_id)]
    response_nav = []
    for item in nav_name:
        nav = [item + await menu_service.nav_name(i["id"]) for i in item]
        response_nav += nav
    return response_nav


def format_media_info(
        video_height: int = 0,
        video_width: int = 0,
        width: int = 0,
        height: int = 0,
        type: str = "",
        key: str = "",
        url: str = "",
        originurl: str = "",
):
    return {
        "videoHeight": video_height,
        "videoWidth": video_width,
        "width": width,
        "height": height,
        "type": type,
        "key": key,
        "url": url,
        "originalUrl": originurl
    }


def format_exif(exif: dict, media_host: str = QINIU_MEDIA_HOST, photo_style=None, video_style=None):
    """"""
    if not photo_style:
        photo_style = '?imageMogr2/auto-orient/quality/75/format/jpg|imageMogr2/auto-orient/thumbnail/660x660'
    if not video_style:
        video_style = '?vframe/jpg/offset/1'
    m_key = exif.get('key', '')
    m_original_url = f'{media_host}/{m_key}'
    m_type_old = exif.get("format", '')
    m_type = exif.get("type", '') or m_type_old
    if m_type.startswith('video'):
        m_url = f'{m_original_url}{video_style}'
    else:
        m_url = f'{m_original_url}{photo_style}'
    return {
        "videoHeight": num_get(exif.get('videoHeight', 0)),
        "videoWidth": num_get(exif.get('videoWidth', 0)),
        "width": num_get(exif.get('width', 0)),
        "height": num_get(exif.get('height', 0)),
        "type": exif.get('type', ''),
        "key": exif.get('key', ''),
        "url": m_url,
        "originalUrl": m_original_url,
    }


async def response_media(media_id):
    """
    获取媒体
    :param media_id:
    :return:
    """

    except_result = {}
    except_result["media"] = format_media_info()
    except_result["desc"] = ""
    except_result["types"] = 0
    except_result["url"] = ""

    media = await mysql.Media.get_or_none(id=media_id)
    try:
        if media.object_type == mysql.Media.Type.photo:
            photo_data = await mysql.Photo.get_or_none(id=media.object_id)
            exif = json.loads(photo_data.file_exif) if photo_data.file_exif else {}
            exif["key"] = photo_data.key or exif.get("key")
            result = {"media": format_exif(exif), "desc": photo_data.text, "type": media.object_type}

            return result

        elif media.object_type == mysql.Media.Type.case:
            media_data = await mysql.Case.get_or_none(id=media.object_id)
            # 子级媒体
            sun_media = await mysql.Media.filter(parent_id=media.id).first()
            photo_data = await mysql.Photo.filter(id=sun_media.object_id).first()
            exif = json.loads(photo_data.file_exif) if photo_data.file_exif else {}
            exif["key"] = photo_data.key or exif.get("key")
            result = {"media": format_exif(exif), "desc": media_data.text}
            if media_data.kind == 1:
                result["type"] = 2
            elif media_data.kind == 2:
                result["type"] = 3
            return result

        elif media.object_type == mysql.Media.Type.video:
            media_data = await mysql.Video.get_or_none(id=media.object_id)
            exif = json.loads(media_data.file_exif) if media_data.file_exif else {}
            exif["key"] = media_data.key or exif.get("key")
            result = {"media": format_exif(exif), "desc": media_data.text, "type": media.object_type}
            return result
        elif media.object_type == mysql.Media.Type.panorama:
            media_data = await mysql.Panorama.get_or_none(id=media.object_id)
            exif = json.loads(media_data.file_exif) if media_data.file_exif else {}
            exif["key"] = media_data.key or exif.get("key")
            result = {"media": format_exif(exif), "desc": media_data.text, "type": media.object_type,
                      "url": media_data.url}
            return result
    except:
        return except_result


async def response_comment(current_user_id: int, comment_id: int, comment: mysql.Comment = None):
    """
    获取格式化的评论
    :param current_user_id:
    :param comment_id:
    :param comment:
    :return:
    """
    c = comment or await mysql.Comment.get_or_none(id=comment_id)
    user = await get_user_base_info(c.user_id)
    nickname = user.nickname if user else ''
    avatar = format_avatar_url(user.avatar if user else '')
    children = []
    c_f = await get_comment_object_first_comment(c.id)
    if c_f:
        c_f_info = await response_second_comment(c_f.id, c_f)
        if c_f_info:
            children.append(c_f_info)
    return {
        'id': c.id,
        'nickname': nickname,
        'avatar': avatar,
        'time': format_datetime(c.created_time),
        'desc': c.text or '',
        'isLiked': await is_like_comment(current_user_id, c.id),
        'likeNumber': c.like_number,
        'replyNumber': c.comment_number,
        'replyList': children,
    }


async def response_second_comment(comment_id: int, comment: mysql.Comment = None):
    """
    获取格式化的二级评论
    :param comment_id:
    :param comment:
    :return:
    """
    c = comment or await mysql.Comment.get_or_none(id=comment_id)
    if not c:
        return
    user_a = await get_user_base_info(c.user_id)
    nickname_a = user_a.nickname if user_a else ''
    avatar_a = format_avatar_url(user_a.avatar if user_a else '')
    user_b = await get_user_base_info(c.reply_revert_comment_user_id)
    nickname_b = user_b.nickname if user_b else ''
    return {
        'id': c.id,
        'aNickname': nickname_a,
        'bNickname': nickname_b,
        'aAvatar': avatar_a,
        'desc': c.text or '',
    }


async def response_manage_media(current_user_id: int, media_id: int, media_host: str = QINIU_MEDIA_HOST):
    """
    图片管理中的媒体格式
    :param current_user_id:
    :param media_id:
    :param media_host:
    :return:
    """
    media = await mysql.Media.get_or_none(id=media_id)
    if media:
        exif = {}
        desc = ''
        url = ''
        m_type = 1
        if media.object_type == mysql.Media.Type.photo:
            data = await mysql.Photo.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                desc = data.text or ''
                m_type = 1
        elif media.object_type == mysql.Media.Type.case:
            case = await mysql.Case.get_or_none(id=media.object_id)
            photo_media = await mysql.Media.filter(parent_id=media.id).first()
            data = await mysql.Photo.get_or_none(id=photo_media.object_id) if photo_media else None
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                if case:
                    desc = case.title or ''
                    if case.kind == 1:
                        m_type = 2
                    elif case.kind == 2:
                        m_type = 3
        elif media.object_type == mysql.Media.Type.video:
            data = await mysql.Video.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                desc = data.text or ''
                m_type = 4
        elif media.object_type == mysql.Media.Type.panorama:
            data = await mysql.Panorama.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                desc = data.text or ''
                url = data.url or ''
                m_type = 5
        has_collect = await is_collect_media(current_user_id, media.id)
        info = {
            'id': media.id,
            'media': format_exif(exif),
            'type': m_type,
            'url': url,
            'desc': desc,
            'hasCollect': has_collect,
            'isSelected': False,
            'isDelete': True if media.is_delete and current_user_id != media.user_id else False
        }
        return info


async def response_detail_media_photo(current_user_id: int, media_id: int, media_host: str = QINIU_MEDIA_HOST,
                                      media: mysql.Media = None, has_user: bool = False):
    """
    获取媒体的图片或视频数据格式
    :param current_user_id:
    :param media_id:
    :param media_host:
    :param media:
    :param has_user:
    :return:
    """
    media = media or await mysql.Media.get_or_none(id=media_id)
    if media:
        exif = {}
        desc = ''
        url = ''
        m_type = 1
        system_tags = []
        if media.object_type == mysql.Media.Type.photo:
            data = await mysql.Photo.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                desc = data.text or ''
                m_type = 1
                system_tags = json.loads(data.system_tags) if data.system_tags else []
        elif media.object_type == mysql.Media.Type.case:
            case = await mysql.Case.get_or_none(id=media.object_id)
            photo_media = await mysql.Media.filter(parent_id=media.id).first()
            data = await mysql.Photo.get_or_none(id=photo_media.object_id) if photo_media else None
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
            if case:
                desc = case.title or ''
                if case.kind == 1:
                    m_type = 2
                elif case.kind == 2:
                    m_type = 3
                system_tags = json.loads(case.system_tags) if case.system_tags else []
        elif media.object_type == mysql.Media.Type.video:
            data = await mysql.Video.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                desc = data.text or ''
                m_type = 4
                system_tags = json.loads(data.system_tags) if data.system_tags else []
        elif media.object_type == mysql.Media.Type.panorama:
            data = await mysql.Panorama.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
                desc = data.text or ''
                url = data.url or ''
                m_type = 5
                system_tags = json.loads(data.system_tags) if data.system_tags else []
        has_collect = await is_collect_media(current_user_id, media.id)

        # 组装标签
        custom_tags = await get_media_custom_tags(current_user_id, media.id)
        tags = [{'name': i, 'type': 2} for i in custom_tags]
        tags.extend([{'name': i, 'type': 1} for i in system_tags])

        info = {
            "id": media.id,
            "media": format_exif(exif),
            "type": m_type,
            "url": url,
            "desc": desc,
            "hasCollect": has_collect,
            "isSelected": False,
            "tags": tags,
            "collectNumber": media.collect_number,
            "commentNumber": media.comment_number,
            "likeNumber": media.like_number,
        }

        if has_user:
            user = await get_user_base_info(media.user_id)
            nickname = user.nickname if user else ''
            avatar = format_avatar_url(user.avatar if user else '')
            a2b = await get_follow_status(current_user_id, media.user_id)
            info.update({
                "nickname": nickname,
                "avatar": avatar,
                "a2b": a2b,
                "userId": media.user_id,
            })
        return info


async def response_detail_media(current_user_id: int, media_id: int, media_host: str = QINIU_MEDIA_HOST,
                                media: mysql.Media = None, photo_limit: int = -1):
    """
    返回详情页的格式
    :param current_user_id:
    :param media_id:
    :param media_host:
    :param media:
    :param photo_limit:
    :return:
    """
    media = media or await mysql.Media.get_or_none(id=media_id)
    if media:
        m_type = 1
        title = ''
        desc = ''
        system_tags = []
        photos = []
        if media.object_type == mysql.Media.Type.photo:
            data = await mysql.Photo.get_or_none(id=media.object_id)
            if data:
                desc = data.text or ''
                m_type = 1
                system_tags = json.loads(data.system_tags) if data.system_tags else []
                media_photo = await response_detail_media_photo(current_user_id, media.id, media_host=media_host, media=media)
                if media_photo:
                    photos.append(media_photo)
        elif media.object_type == mysql.Media.Type.case:
            case = await mysql.Case.get_or_none(id=media.object_id)
            if case:
                title = case.title or ''
                desc = case.text or ''
                if case.kind == 1:
                    m_type = 2
                elif case.kind == 2:
                    m_type = 3
                system_tags = json.loads(case.system_tags) if case.system_tags else []
                if photo_limit != -1:
                    photo_medias = await mysql.Media.filter(parent_id=media.id).order_by('created_time').limit(photo_limit)
                else:
                    photo_medias = await mysql.Media.filter(parent_id=media.id).order_by('created_time')
                for photo_media in photo_medias:
                    photo_info = await response_detail_media_photo(current_user_id, photo_media.id, media_host=media_host, media=photo_media)
                    photos.append(photo_info)

        elif media.object_type == mysql.Media.Type.video:
            data = await mysql.Video.get_or_none(id=media.object_id)
            if data:
                m_type = 4
                desc = data.text or ''
                system_tags = json.loads(data.system_tags) if data.system_tags else []
                media_photo = await response_detail_media_photo(current_user_id, media.id, media_host=media_host, media=media, has_user=True)
                if media_photo:
                    photos.append(media_photo)
        elif media.object_type == mysql.Media.Type.panorama:
            data = await mysql.Panorama.get_or_none(id=media.object_id)
            if data:
                m_type = 5
                desc = data.text or ''
                media_photo = await response_detail_media_photo(current_user_id, media.id, media_host=media_host, media=media, has_user=True)
                if media_photo:
                    photos.append(media_photo)
        has_like = await is_like_media(current_user_id, media.id)
        has_collect = await is_collect_media(current_user_id, media.id)

        # 组装标签
        custom_tags = await get_media_custom_tags(current_user_id, media.id)
        tags = [{'name': i, 'type': 2} for i in custom_tags]
        tags.extend([{'name': i, 'type': 1} for i in system_tags])

        # 用户信息
        user = await get_user_base_info(media.user_id)
        nickname = user.nickname if user else ''
        avatar = format_avatar_url(user.avatar if user else '')
        data = {
            'id': media.id,
            'title': title,
            'desc': desc,
            'source': {
                'username': '',
                'website': '',
                'url': '',
            },
            'tags': tags,
            'user': {
                'id': media.user_id,
                'nickname': nickname,
                'avatar': avatar,
                'time': '',
                'a2b': await get_follow_status(current_user_id, media.user_id),
            },
            'likeNumber': media.like_number,
            'commentNumber': media.comment_number,
            'isLiked': has_like,
            'collectNumber': media.collect_number,
            'hasCollect': has_collect,
            'photos': photos,
            'type': m_type,
        }
        return data


async def response_media_cover(media_id: int, media_host: str = QINIU_MEDIA_HOST):
    """
    媒体封面格式
    :param media_id:
    :param media_host:
    :return:
    """
    media = await mysql.Media.get_or_none(id=media_id)
    if media:
        exif = {}
        if media.object_type == mysql.Media.Type.photo:
            data = await mysql.Photo.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
        elif media.object_type == mysql.Media.Type.case:
            photo_media = await mysql.Media.filter(parent_id=media.id).first()
            data = await mysql.Photo.get_or_none(id=photo_media.object_id) if photo_media else None
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
        elif media.object_type == mysql.Media.Type.video:
            data = await mysql.Video.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
        elif media.object_type == mysql.Media.Type.panorama:
            data = await mysql.Panorama.get_or_none(id=media.object_id)
            if data:
                exif = json.loads(data.file_exif or '{}')
                exif["key"] = data.key or exif.get("key")
        info = {
            'id': media.id,
            'media': format_exif(exif),
        }
        return info


async def response_folder(current_user_id: int, folder_id: int, media_host: str = QINIU_MEDIA_HOST):
    """
    返回文件夹的格式
    :param current_user_id:
    :param folder_id:
    :param media_host:
    :return:
    """
    f_id = folder_id
    m_list = []
    if folder_id == -1:
        name = '回收站'
        folder_types = 4
        photo_number = await get_user_recycle_count(current_user_id)
        f_id = -1
        user_recycles = await get_user_recycles(current_user_id, offset=0, limit=4)

        for user_recycle in user_recycles:
            info = await response_media_cover(user_recycle.media_id)
            if info:
                exif = info.get('media', {})
                m_key = exif.get('key', '')
                if m_key:
                    m_list.append(format_exif(exif))

    else:
        folder = await get_folder(folder_id)
        if not folder:
            return
        name = folder.name or ''
        folder_types = folder.folder_types
        photo_number = folder.sum_media_number
        folder_covers = await get_folder_covers(folder_id)
        exif_list = json.loads(folder_covers.covers) if folder_covers and folder_covers.covers else []
        for exif in exif_list:
            m_key = exif.get('key', '')
            if m_key:
                m_list.append(format_exif(exif))

    data = {
        "id": f_id,
        "name": name,
        "type": folder_types,
        "photoNumber": photo_number,
        "medias": m_list,
    }
    return data


async def response_navs(query_menu_id, query_sub_menu_ids=None):
    """
    获取二级菜单列表
    :param query_menu_id: 选中的一级菜单编号
    :param query_sub_menu_ids: 选中的二级菜单编号列表
    :return:
    """
    if query_sub_menu_ids is None:
        query_sub_menu_ids = []
    query_sub_menu_ids_set = set(query_sub_menu_ids)
    # 获取二级菜单
    menus = await nav_name(query_menu_id)
    need_navs = []
    for menu in menus:
        sub_menus = await nav_name(menu.get('id'))
        sub_navs = []
        sub_select_count = 0
        for sub_menu in sub_menus:
            sub_menu_id = sub_menu.get('id')
            is_selected = sub_menu_id in query_sub_menu_ids_set
            if is_selected:
                sub_select_count += 1
            sub_menu['isSelected'] = sub_menu_id in query_sub_menu_ids_set
            sub_navs.append(sub_menu)
        menu['isSelected'] = sub_select_count == 0
        navs = [menu]
        navs.extend(sub_navs)
        need_navs.append(navs)
    return need_navs


async def response_user(current_user_id: int, user_id: int):
    """
    获取用户格式
    :param current_user_id:
    :param user_id:
    :return:
    """
    user = await get_user_base_info(user_id)
    if user:
        nickname = user.nickname if user else ''
        avatar = format_avatar_url(user.avatar if user else '')
        a2b = await get_follow_status(current_user_id, user_id)
        b2a = await get_follow_status(user_id, current_user_id)
        data = {
            "id": user.id,
            "nickname": nickname,
            "avatar": avatar,
            "a2b": a2b,
            "b2a": b2a,
        }
        return data
